home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / pcl / docs.lha / cmu-user / cmu-user.info-6 < prev    next >
Text File  |  1992-08-05  |  51KB  |  1,192 lines

  1. Info file: cmu-user.info,    -*-Text-*-
  2. produced by latexinfo-format-buffer
  3. from file: cmu-user.tex
  4.  
  5.  
  6. 
  7. File: cmu-user.info  Node: Inline Expansion Recording, Prev: Inline Expansion, Up: Inline Expansion, Next: Semi-Inline Expansion
  8.  
  9. Inline Expansion Recording
  10. --------------------------
  11.  
  12.  
  13. Inline expansion requires that the source for the inline expanded
  14. function to be available when calls to the function are compiled.  The
  15. compiler doesn't remember the inline expansion for every function, since
  16. that would take an excessive about of space.  Instead, the programmer
  17. must tell the compiler to record the inline expansion before the
  18. definition of the inline expanded function is compiled.  This is done by
  19. globally declaring the function inline before the function is defined,
  20. by using the `inline' and `extensions:maybe-inline' (?)  declarations.
  21.  
  22. In addition to recording the inline expansion of inline functions at the
  23. time the function is compiled, `compile-file' also puts the inline
  24. expansion in the output file.  When the output file is loaded, the
  25. inline expansion is made available for subsequent compilations; there is
  26. no need to compile the definition again to record the inline expansion.
  27.  
  28. If a function is declared inline, but no expansion is recorded, then the
  29. compiler will give an efficiency note like:
  30.      
  31.      Note: MYFUN is declared inline, but has no expansion.
  32.  
  33. When you get this note, check that the `inline' declaration and the
  34. definition appear before the calls that are to be inline expanded.  This
  35. note will also be given if the inline expansion for a `defun' could not
  36. be recorded because the `defun' was in a non-null lexical environment.
  37.  
  38. 
  39. File: cmu-user.info  Node: Semi-Inline Expansion, Prev: Inline Expansion Recording, Up: Inline Expansion, Next: The Maybe-Inline Declaration
  40.  
  41. Semi-Inline Expansion
  42. ---------------------
  43.  
  44.  
  45. Python supports SEMI-INLINE functions.  Semi-inline expansion shares a
  46. single copy of a function across all the calls in a component by
  47. converting the inline expansion into a local function (*Note Local
  48. Call::.)  This takes up less space when there are multiple calls, but
  49. also provides less opportunity for context dependent optimization.  When
  50. there is only one call, the result is identical to normal inline
  51. expansion.  Semi-inline expansion is done when the `space' optimization
  52. quality is `0', and the function has been declared
  53. `extensions:maybe-inline'.
  54.  
  55. This mechanism of inline expansion combined with local call also allows
  56. recursive functions to be inline expanded.  If a recursive function is
  57. declared `inline', calls will actually be compiled semi-inline.
  58. Although recursive functions are often so complex that there is little
  59. advantage to semi-inline expansion, it can still be useful in the same
  60. sort of cases where normal inline expansion is especially advantageous,
  61. i.e. functions where the calling context can help a lot.
  62.  
  63. 
  64. File: cmu-user.info  Node: The Maybe-Inline Declaration, Prev: Semi-Inline Expansion, Up: Inline Expansion
  65.  
  66. The Maybe-Inline Declaration
  67. ----------------------------
  68.  
  69.  
  70. The `extensions:maybe-inline' declaration is a CMU Common Lisp
  71. extension.  It is similar to `inline', but indicates that inline
  72. expansion may sometimes be desirable, rather than saying that inline
  73. expansion should almost always be done.  When used in a global
  74. declaration, `extensions:maybe-inline' causes the expansion for the
  75. named functions to be recorded, but the functions aren't actually inline
  76. expanded unless `space' is `0' or the function is eventually (perhaps
  77. locally) declared `inline'.
  78.  
  79. Use of the `extensions:maybe-inline' declaration followed by the `defun' is
  80. preferable to the standard idiom of:
  81.      
  82.      (proclaim '(inline myfun))
  83.      (defun myfun () ...)
  84.      (proclaim '(notinline myfun))
  85.      
  86.      ;;; Any calls to `myfun' here are not inline expanded.
  87.      
  88.      (defun somefun ()
  89.        (declare (inline myfun))
  90.        ;;
  91.        ;; Calls to `myfun' here are inline expanded.
  92.        ...)
  93.  
  94. The problem with using `notinline' in this way is that in CMU Common
  95. Lisp it does more than just suppress inline expansion, it also forbids
  96. the compiler to use any knowledge of `myfun' until a later `inline'
  97. declaration overrides the `notinline'.  This prevents compiler warnings
  98. about incorrect calls to the function, and also prevents block
  99. compilation.
  100.  
  101. The `extensions:maybe-inline' declaration is used like this:
  102.      
  103.      (proclaim '(extensions:maybe-inline myfun))
  104.      (defun myfun () ...)
  105.      
  106.      ;;; Any calls to `myfun' here are not inline expanded.
  107.      
  108.      (defun somefun ()
  109.        (declare (inline myfun))
  110.        ;;
  111.        ;; Calls to `myfun' here are inline expanded.
  112.        ...)
  113.      
  114.      (defun someotherfun ()
  115.        (declare (optimize (space 0)))
  116.        ;;
  117.        ;; Calls to `myfun' here are expanded semi-inline.
  118.        ...)
  119.  
  120. In this example, the use of `extensions:maybe-inline' causes the
  121. expansion to be recorded when the `defun' for `somefun' is compiled, and
  122. doesn't waste space through doing inline expansion by default.  Unlike
  123. `notinline', this declaration still allows the compiler to assume that
  124. the known definition really is the one that will be called when giving
  125. compiler warnings, and also allows the compiler to do semi-inline
  126. expansion when the policy is appropriate.
  127.  
  128. When the goal is merely to control whether inline expansion is done by
  129. default, it is preferable to use `extensions:maybe-inline' rather than
  130. `notinline'.  The `notinline' declaration should be reserved for those
  131. special occasions when a function may be redefined at run-time, so the
  132. compiler must be told that the obvious definition of a function is not
  133. necessarily the one that will be in effect at the time of the call.
  134.  
  135.  
  136. 
  137. File: cmu-user.info  Node: Object Representation, Prev: Inline Expansion, Up: Advanced Compiler Use and Efficiency Hints, Next: Numbers
  138.  
  139. Object Representation
  140. =====================
  141.  
  142.  
  143. A somewhat subtle aspect of writing efficient CMU Common Lisp programs
  144. is choosing the correct data structures so that the underlying objects
  145. can be implemented efficiently.  This is partly because of the need for
  146. multiple representations for a given value (?), but is also due to the
  147. sheer number of object types that CMU Common Lisp has built in.  The
  148. number of possible representations complicates the choice of a good
  149. representation because semantically similar objects may vary in their
  150. efficiency depending on how the program operates on them.
  151.  
  152. * Menu:
  153.  
  154. * Think Before You Use a List::  
  155. * Structures::                  
  156. * Arrays::                      
  157. * Vectors::                     
  158. * Bit-Vectors::                 
  159. * Hashtables::                  
  160.  
  161.  
  162. 
  163. File: cmu-user.info  Node: Think Before You Use a List, Prev: Object Representation, Up: Object Representation, Next: Structures
  164.  
  165. Think Before You Use a List
  166. ---------------------------
  167.  
  168.  
  169. Although Lisp's creator seemed to think that it was for LISt Processing,
  170. the astute observer may have noticed that the chapter on list
  171. manipulation makes up less that three percent of Common Lisp: the
  172. Language II.  The language has grown since Lisp 1.5 -- new data types
  173. supersede lists for many purposes.
  174.  
  175. 
  176. File: cmu-user.info  Node: Structures, Prev: Think Before You Use a List, Up: Object Representation, Next: Arrays
  177.  
  178. Structures
  179. ----------
  180.  
  181. One of the best ways of building complex data structures is to define
  182. appropriate structure types using defstruct.  In Python, access of
  183. structure slots is always at least as fast as list or vector access, and
  184. is usually faster.  In comparison to a list representation of a tuple,
  185. structures also have a space advantage.
  186.  
  187. Even if structures weren't more efficient than other representations, structure
  188. use would still be attractive because programs that use structures in
  189. appropriate ways are much more maintainable and robust than programs written
  190. using only lists.  For example:
  191.      
  192.      (rplaca (caddr (cadddr x)) (caddr y))
  193.  
  194. could have been written using structures in this way:
  195.      
  196.      (setf (beverage-flavor (astronaut-beverage x)) (beverage-flavor y))
  197.  
  198. The second version is more maintainable because it is easier to
  199. understand what it is doing.  It is more robust because structures
  200. accesses are type checked.  An `astronaut' will never be confused with a
  201. `beverage', and the result of `beverage-flavor' is always a flavor.  See
  202. sections *Note Structure Types:: and *Note The Freeze-Type Declaration::
  203. for more information about structure types.  *Note Type Inference:: for
  204. a number of examples that make clear the advantages of structure typing.
  205.  
  206. Note that the structure definition should be compiled before any uses of
  207. its accessors or type predicate so that these function calls can be
  208. efficiently open-coded.
  209.  
  210. 
  211. File: cmu-user.info  Node: Arrays, Prev: Structures, Up: Object Representation, Next: Vectors
  212.  
  213. Arrays
  214. ------
  215.  
  216.  
  217. Arrays are often the most efficient representation for collections of objects
  218. because:
  219.      
  220.    * Array representations are often the most compact.  An array is
  221.      always more compact than a list containing the same number of
  222.      elements.
  223.      
  224.    * Arrays allow fast constant-time access.
  225.      
  226.    * Arrays are easily destructively modified, which can reduce consing.
  227.      
  228.    * Array element types can be specialized, which reduces both overall size and
  229.      consing (?.)
  230.  
  231.  
  232.  
  233. Access of arrays that are not of type `simple-array' is less efficient,
  234. so declarations are appropriate when an array is of a simple type like
  235. `simple-string' or `simple-bit-vector'.  Arrays are almost always
  236. simple, but the compiler may not be able to prove simpleness at every
  237. use.  The only way to get a non-simple array is to use the
  238. :displaced-to, :fill-pointer or `adjustable' arguments to `make-array'.
  239. If you don't use these hairy options, then arrays can always be declared
  240. to be simple.
  241.  
  242. Because of the many specialized array types and the possibility of
  243. non-simple arrays, array access is much like generic arithmetic (?).  In
  244. order for array accesses to be efficiently compiled, the element type
  245. and simpleness of the array must be known at compile time.  If there is
  246. inadequate information, the compiler is forced to call a generic array
  247. access routine.  You can detect inefficient array accesses by enabling
  248. efficiency notes, ?.
  249.  
  250. 
  251. File: cmu-user.info  Node: Vectors, Prev: Arrays, Up: Object Representation, Next: Bit-Vectors
  252.  
  253. Vectors
  254. -------
  255.  
  256.  
  257. Vectors (one dimensional arrays) are particularly useful, since in
  258. addition to their obvious array-like applications, they are also well
  259. suited to representing sequences.  In comparison to a list
  260. representation, vectors are faster to access and take up between two and
  261. sixty-four times less space (depending on the element type.)  As with
  262. arbitrary arrays, the compiler needs to know that vectors are not
  263. complex, so you should use `simple-string' in preference to `string',
  264. etc.
  265.  
  266. The only advantage that lists have over vectors for representing
  267. sequences is that it is easy to change the length of a list, add to it
  268. and remove items from it.  Likely signs of archaic, slow lisp code are
  269. `nth' and `nthcdr'.  If you are using these functions you should
  270. probably be using a vector.
  271.  
  272. 
  273. File: cmu-user.info  Node: Bit-Vectors, Prev: Vectors, Up: Object Representation, Next: Hashtables
  274.  
  275. Bit-Vectors
  276. -----------
  277.  
  278.  
  279. Another thing that lists have been used for is set manipulation.  In
  280. applications where there is a known, reasonably small universe of items
  281. bit-vectors can be used to improve performance.  This is much less
  282. convenient than using lists, because instead of symbols, each element in
  283. the universe must be assigned a numeric index into the bit vector.
  284. Using a bit-vector will nearly always be faster, and can be tremendously
  285. faster if the number of elements in the set is not small.  The logical
  286. operations on `simple-bit-vector's are efficient, since they operate on
  287. a word at a time.
  288.  
  289.  
  290. 
  291. File: cmu-user.info  Node: Hashtables, Prev: Bit-Vectors, Up: Object Representation
  292.  
  293. Hashtables
  294. ----------
  295.  
  296.  
  297. Hashtables are an efficient and general mechanism for maintaining
  298. associations such as the association between an object and its name.
  299. Although hashtables are usually the best way to maintain associations,
  300. efficiency and style considerations sometimes favor the use of an
  301. association list (a-list).
  302.  
  303. `assoc' is fairly fast when the TEST argument is `eq' or `eql' and there
  304. are only a few elements, but the time goes up in proportion with the
  305. number of elements.  In contrast, the hash-table lookup has a somewhat
  306. higher overhead, but the speed is largely unaffected by the number of
  307. entries in the table.  For an `equal' hash-table or alist, hash-tables
  308. have an even greater advantage, since the test is more expensive.
  309. Whatever you do, be sure to use the most restrictive test function
  310. possible.
  311.  
  312. The style argument observes that although hash-tables and alists
  313. overlap in function, they do not do all things equally well.
  314.      
  315.    * Alists are good for maintaining scoped environments.  They were
  316.      originally invented to implement scoping in the Lisp interpreter,
  317.      and are still used for this in Python.  With an alist one can
  318.      non-destructively change an association simply by consing a new
  319.      element on the front.  This is something that cannot be done with
  320.      hash-tables.
  321.      
  322.    * Hashtables are good for maintaining a global association.  The
  323.      value associated with an entry can easily be changed with `setf'.
  324.      With an alist, one has to go through contortions, either
  325.      `rplacd''ing the cons if the entry exists, or pushing a new one if
  326.      it doesn't.  The side-effecting nature of hash-table operations is
  327.      an advantage here.
  328.  
  329.  
  330.  
  331. Historically, symbol property lists were often used for global name
  332. associations.  Property lists provide an awkward and error-prone
  333. combination of name association and record structure.  If you must use
  334. the property list, please store all the related values in a single
  335. structure under a single property, rather than using many properties.
  336. This makes access more efficient, and also adds a modicum of typing and
  337. abstraction.  *Note More About Types in Python:: for information on
  338. types in CMU Common Lisp.
  339.  
  340.         
  341. 
  342. File: cmu-user.info  Node: Numbers, Prev: Object Representation, Up: Advanced Compiler Use and Efficiency Hints, Next: General Efficiency Hints
  343.  
  344. Numbers
  345. =======
  346.  
  347.  
  348. Numbers are interesting because numbers are one of the few Common Lisp
  349. data types that have direct support in conventional hardware.  If a
  350. number can be represented in the way that the hardware expects it, then
  351. there is a big efficiency advantage.
  352.  
  353. Using hardware representations is problematical in Common Lisp due to dynamic typing
  354. (where the type of a value may be unknown at compile time.)  It is possible to
  355. compile code for statically typed portions of a Common Lisp program with efficiency
  356. comparable to that obtained in statically typed languages such as C, but not
  357. all Common Lisp implementations succeed.  There are two main barriers to efficient
  358. numerical code in Common Lisp:
  359.      
  360.    * The compiler must prove that the numerical expression is in fact statically
  361.      typed, and
  362.      
  363.    * The compiler must be able to somehow reconcile the conflicting
  364.      demands of the hardware mandated number representation with the
  365.      Common Lisp requirements of dynamic typing and garbage-collecting
  366.      dynamic storage allocation.
  367.  
  368.  
  369. Because of its type inference (*Note Type Inference::) and efficiency
  370. notes (?), Python is better than conventional Common Lisp compilers at
  371. ensuring that numerical expressions are statically typed.  Python also
  372. goes somewhat farther than existing compilers in the area of allowing
  373. native machine number representations in the presence of garbage
  374. collection.
  375.  
  376. * Menu:
  377.  
  378. * Descriptors::                 
  379. * Non-Descriptor Representations::  
  380. * Variables::                   
  381. * Generic Arithmetic::          
  382. * Fixnums::                     
  383. * Word Integers::               
  384. * Floating Point Efficiency::   
  385. * Specialized Arrays::          
  386. * Interactions With Local Call::  
  387. * Representation of Characters::  
  388.  
  389.  
  390. 
  391. File: cmu-user.info  Node: Descriptors, Prev: Numbers, Up: Numbers, Next: Non-Descriptor Representations
  392.  
  393. Descriptors
  394. -----------
  395.  
  396.  
  397. Common Lisp's dynamic typing requires that it be possible to represent any value
  398. with a fixed length object, known as a DESCRIPTOR.  This fixed-length
  399. requirement is implicit in features such as:
  400.      
  401.    * Data types (like `simple-vector') that can contain any type of object, and
  402.      that can be destructively modified to contain different objects (of possibly
  403.      different types.)
  404.      
  405.    * Functions that can be called with any type of argument, and that
  406.      can be redefined at run time.
  407.  
  408.  
  409. In order to save space, a descriptor is invariably represented as a
  410. single word.  Objects that can be directly represented in the descriptor
  411. itself are said to be IMMEDIATE.  Descriptors for objects larger than
  412. one word are in reality pointers to the memory actually containing the
  413. object.
  414.  
  415. Representing objects using pointers has two major disadvantages:
  416.      
  417.    * The memory pointed to must be allocated on the heap, so it must
  418.      eventually be freed by the garbage collector.  Excessive heap
  419.      allocation of objects (or "consing") is inefficient in several
  420.      ways.  ?.
  421.      
  422.    * Representing an object in memory requires the compiler to emit
  423.      additional instructions to read the actual value in from memory,
  424.      and then to write the value back after operating on it.
  425.  
  426.  
  427. The introduction of garbage collection makes things even worse, since the
  428. garbage collector must be able to determine whether a descriptor is an
  429. immediate object or a pointer.  This requires that a few bits in each
  430. descriptor be dedicated to the garbage collector.  The loss of a few bits
  431. doesn't seem like much, but it has a major efficiency implication -- objects
  432. whose natural machine representation is a full word (integers and
  433. single-floats) cannot have an immediate representation.  So the compiler is
  434. forced to use an unnatural immediate representation (such as `fixnum') or a
  435. natural pointer representation (with the attendant consing overhead.)
  436.  
  437.  
  438. 
  439. File: cmu-user.info  Node: Non-Descriptor Representations, Prev: Descriptors, Up: Numbers, Next: Variables
  440.  
  441. Non-Descriptor Representations
  442. ------------------------------
  443.  
  444.  
  445. From the discussion above, we can see that the standard descriptor
  446. representation has many problems, the worst being number consing.
  447. Common Lisp compilers try to avoid these descriptor efficiency problems by using
  448. NON-DESCRIPTOR representations.  A compiler that uses non-descriptor
  449. representations can compile this function so that it does no number consing:
  450.      
  451.      (defun multby (vec n)
  452.        (declare (type (simple-array single-float (*)) vec)
  453.                 (single-float n))
  454.        (dotimes (i (length vec))
  455.          (setf (aref vec i)
  456.                (* n (aref vec i)))))
  457.  
  458. If a descriptor representation were used, each iteration of the loop
  459. might cons two floats and do three times as many memory references.
  460.  
  461. As its negative definition suggests, the range of possible
  462. non-descriptor representations is large.  The performance improvement
  463. from non-descriptor representation depends upon both the number of types
  464. that have non-descriptor representations and the number of contexts in
  465. which the compiler is forced to use a descriptor representation.
  466.  
  467. Many Common Lisp compilers support non-descriptor representations for float types
  468. such as `single-float' and `double-float' (section ?.)
  469. Python adds support for full word integers (?),
  470. characters (?) and system-area pointers (unconstrained
  471. pointers, ?.)  Many Common Lisp compilers
  472. support non-descriptor representations for variables (section
  473. ?) and array elements (section ?.)
  474. Python adds support for non-descriptor arguments and return values in local
  475. call (?).
  476. 
  477. File: cmu-user.info  Node: Variables, Prev: Non-Descriptor Representations, Up: Numbers, Next: Generic Arithmetic
  478.  
  479. Variables
  480. ---------
  481.  
  482.  
  483. In order to use a non-descriptor representation for a variable or expression
  484. intermediate value, the compiler must be able to prove that the value is always
  485. of a particular type having a non-descriptor representation.  Type inference
  486. (*Note Type Inference::) often needs some help from user-supplied
  487. declarations.  The best kind of type declaration is a variable type declaration
  488. placed at the binding point:
  489.      
  490.      (let ((x (car l)))
  491.        (declare (single-float x))
  492.        ...)
  493.  
  494. Use of `the', or of variable declarations not at the binding form is
  495. insufficient to allow non-descriptor representation of the variable -- with
  496. these declarations it is not certain that all values of the variable are of the
  497. right type.  It is sometimes useful to introduce a gratuitous binding that
  498. allows the compiler to change to a non-descriptor representation, like:
  499.      
  500.      (etypecase x
  501.        ((signed-byte 32)
  502.         (let ((x x))
  503.           (declare (type (signed-byte 32) x)) 
  504.           ...))
  505.        ...)
  506.  
  507. The declaration on the inner `x' is necessary here due to a phase
  508. ordering problem.  Although the compiler will eventually prove that the
  509. outer `x' is a `(signed-byte 32)' within that `etypecase' branch, the
  510. inner `x' would have been optimized away by that time.  Declaring the
  511. type makes let optimization more cautious.
  512.  
  513. Note that storing a value into a global (or `special') variable always
  514. forces a descriptor representation.  Wherever possible, you should
  515. operate only on local variables, binding any referenced globals to local
  516. variables at the beginning of the function, and doing any global
  517. assignments at the end.
  518.  
  519. Efficiency notes signal use of inefficient representations, so programmer's
  520. needn't continuously worry about the details of representation selection (?.)
  521.  
  522. 
  523. File: cmu-user.info  Node: Generic Arithmetic, Prev: Variables, Up: Numbers, Next: Fixnums
  524.  
  525. Generic Arithmetic
  526. ------------------
  527.  
  528.  
  529. In CMU Common Lisp, arithmetic operations are GENERIC. (9) (*Note
  530. Generic Arithmetic-Footnotes::) The `+' function can be passed
  531. `fixnum's, `bignum's, `ratio's, and various kinds of `float's and
  532. `complex'es, in any combination.  In addition to the inherent complexity
  533. of `bignum' and `ratio' operations, there is also a lot of overhead in
  534. just figuring out which operation to do and what contagion and
  535. canonicalization rules apply.  The complexity of generic arithmetic is
  536. so great that it is inconceivable to open code it.  Instead, the
  537. compiler does a function call to a generic arithmetic routine, consuming
  538. many instructions before the actual computation even starts.
  539.  
  540. This is ridiculous, since even Common Lisp programs do a lot of arithmetic, and the
  541. hardware is capable of doing operations on small integers and floats with a
  542. single instruction.  To get acceptable efficiency, the compiler special-cases
  543. uses of generic arithmetic that are directly implemented in the hardware.  In
  544. order to open code arithmetic, several constraints must be met:
  545.      
  546.    * All the arguments must be known to be a good type of number.
  547.      
  548.    * The result must be known to be a good type of number.
  549.      
  550.    * Any intermediate values such as the result of `(+ a b)' in the call
  551.      `(+ a b c)' must be known to be a good type of number.
  552.      
  553.    * All the above numbers with good types must be of the SAME good
  554.      type.  Don't try to mix integers and floats or different float
  555.      formats.
  556.  
  557.  
  558. The "good types" are `(signed-byte 32)', `(unsigned-byte 32)',
  559. `single-float' and `double-float'.  See sections ?, ? and ? for more
  560. discussion of good numeric types.
  561.  
  562. `float' is not a good type, since it might mean either `single-float' or
  563. `double-float'.  `integer' is not a good type, since it might mean
  564. `bignum'.  `rational' is not a good type, since it might mean `ratio'.
  565. Note however that these types are still useful in declarations, since
  566. type inference may be able to strengthen a weak declaration into a good
  567. one, when it would be at a loss if there was no declaration at all
  568. (*Note Type Inference::).  The `integer' and `unsigned-byte' (or
  569. non-negative integer) types are especially useful in this regard, since
  570. they can often be strengthened to a good integer type.
  571.  
  572. Arithmetic with `complex' numbers is inefficient in comparison to float and
  573. integer arithmetic.  Complex numbers are always represented with a pointer
  574. descriptor (causing consing overhead), and complex arithmetic is always closed
  575. coded using the general generic arithmetic functions.  But arithmetic with
  576. complex types such as:
  577.      
  578.      (complex float)
  579.      (complex fixnum)
  580.  
  581. is still faster than `bignum' or `ratio' arithmetic, since the
  582. implementation is much simpler.
  583.  
  584. Note: don't use `/' to divide integers unless you want the overhead of
  585. rational arithmetic.  Use `truncate' even when you know that the
  586. arguments divide evenly.
  587.  
  588. You don't need to remember all the rules for how to get open-coded
  589. arithmetic, since efficiency notes will tell you when and where there is
  590. a problem -- ?.
  591.  
  592.  
  593. 
  594. File: cmu-user.info  Node: Generic Arithmetic-Footnotes, Up: Generic Arithmetic
  595.  
  596. (9) As Steele notes in CLTL II, this is a generic conception of generic,
  597. and is not to be confused with the CLOS concept of a generic function.
  598.  
  599. 
  600. File: cmu-user.info  Node: Fixnums, Prev: Generic Arithmetic, Up: Numbers, Next: Word Integers
  601.  
  602. Fixnums
  603. -------
  604.  
  605.  
  606. A fixnum is a "FIXed precision NUMber".  In modern Common Lisp
  607. implementations, fixnums can be represented with an immediate
  608. descriptor, so operating on fixnums requires no consing or memory
  609. references.  Clever choice of representations also allows some
  610. arithmetic operations to be done on fixnums using hardware supported
  611. word-integer instructions, somewhat reducing the speed penalty for using
  612. an unnatural integer representation.
  613.  
  614. It is useful to distinguish the `fixnum' type from the fixnum
  615. representation of integers.  In Python, there is absolutely nothing
  616. magical about the `fixnum' type in comparison to other finite integer
  617. types.  `fixnum' is equivalent to (is defined with `deftype' to be)
  618. `(signed-byte 30)'.  `fixnum' is simply the largest subset of integers
  619. that can be represented using an immediate fixnum descriptor.
  620.  
  621. Unlike in other CMU Common Lisp compilers, it is in no way desirable to use the
  622. `fixnum' type in declarations in preference to more restrictive integer types
  623. such as `bit', `(integer -43 7)' and `(unsigned-byte 8)'.  Since
  624. Python does understand these integer types, it is preferable to use the more
  625. restrictive type, as it allows better type inference (*Note Operation Specific Type Inference::.)
  626.  
  627. The small, efficient fixnum is contrasted with bignum, or "BIG NUMber".
  628. This is another descriptor representation for integers, but this time a
  629. pointer representation that allows for arbitrarily large integers.
  630. Bignum operations are less efficient than fixnum operations, both
  631. because of the consing and memory reference overheads of a pointer
  632. descriptor, and also because of the inherent complexity of extended
  633. precision arithmetic.  While fixnum operations can often be done with a
  634. single instruction, bignum operations are so complex that they are
  635. always done using generic arithmetic.
  636.  
  637. A crucial point is that the compiler will use generic arithmetic if
  638. it can't PROVE that all the arguments, intermediate values, and results are
  639. fixnums.  With bounded integer types such as `fixnum', the result type proves
  640. to be especially problematical, since these types are not closed under
  641. common arithmetic operations such as `+', `-', `*' and `/'.  For
  642. example, `(1+ (the fixnum x))' does not necessarily evaluate to a
  643. `fixnum'.  Bignums were added to Common Lisp to get around this problem, but they
  644. really just transform the correctness problem "if this add overflows, you will
  645. get the wrong answer" to the efficiency problem "if this add MIGHT overflow
  646. then your program will run slowly (because of generic arithmetic.)"
  647.  
  648. There is just no getting around the fact that the hardware only directly
  649. supports short integers.  To get the most efficient open coding, the
  650. compiler must be able to prove that the result is a good integer type.
  651. This is an argument in favor of using more restrictive integer types:
  652. `(1+ (the fixnum x))' may not always be a `fixnum', but `(1+ (the
  653. (unsigned-byte 8) x))' always is.  Of course, you can also assert the
  654. result type by putting in lots of `the' declarations and then compiling
  655. with `safety' `0'.
  656.  
  657. 
  658. File: cmu-user.info  Node: Word Integers, Prev: Fixnums, Up: Numbers, Next: Floating Point Efficiency
  659.  
  660. Word Integers
  661. -------------
  662.  
  663.  
  664. Python is unique in its efficient implementation of arithmetic
  665. on full-word integers through non-descriptor representations and open coding.
  666. Arithmetic on any subtype of these types:
  667.      
  668.      (signed-byte 32)
  669.      (unsigned-byte 32)
  670.  
  671. is reasonably efficient, although subtypes of `fixnum' remain somewhat
  672. more efficient.
  673.  
  674. If a word integer must be represented as a descriptor, then the `bignum'
  675. representation is used, with its associated consing overhead.  The
  676. support for word integers in no way changes the language semantics, it
  677. just makes arithmetic on small bignums vastly more efficient.  It is
  678. fine to do arithmetic operations with mixed `fixnum' and word integer
  679. operands; just declare the most specific integer type you can, and let
  680. the compiler decide what representation to use.
  681.  
  682. In fact, to most users, the greatest advantage of word integer
  683. arithmetic is that it effectively provides a few guard bits on the
  684. fixnum representation.  If there are missing assertions on intermediate
  685. values in a fixnum expression, the intermediate results can usually be
  686. proved to fit in a word.  After the whole expression is evaluated, there
  687. will often be a fixnum assertion on the final result, allowing creation
  688. of a fixnum result without even checking for overflow.
  689.  
  690. The remarks in section *Note Fixnums:: about fixnum result type also
  691. apply to word integers; you must be careful to give the compiler enough
  692. information to prove that the result is still a word integer.  This
  693. time, though, when we blow out of word integers we land in into generic
  694. bignum arithmetic, which is much worse than sleazing from `fixnum's to
  695. word integers.  Note that mixing `(unsigned-byte 32)' arguments with
  696. arguments of any signed type (such as `fixnum') is a no-no, since the
  697. result might not be unsigned.
  698.  
  699. 
  700. File: cmu-user.info  Node: Floating Point Efficiency, Prev: Word Integers, Up: Numbers, Next: Specialized Arrays
  701.  
  702. Floating Point Efficiency
  703. -------------------------
  704.  
  705.  
  706. Arithmetic on objects of type `single-float' and `double-float' is
  707. efficiently implemented using non-descriptor representations and open
  708. coding.  As for integer arithmetic, the arguments must be known to be of
  709. the same float type.  Unlike for integer arithmetic, the results and
  710. intermediate values usually take care of themselves due to the rules of
  711. float contagion, i.e.  `(1+ (the single-float x))' is always a
  712. `single-float'.
  713.  
  714. Although they are not specially implemented, `short-float' and
  715. `long-float' are also acceptable in declarations, since they are
  716. synonyms for the `single-float' and `double-float' types, respectively.
  717. It is harmless to use list-style float type specifiers such as
  718. `(single-float 0.0 1.0)', but Python currently makes little use of
  719. bounds on float types.
  720.  
  721. When a float must be represented as a descriptor, a pointer
  722. representation is used, creating consing overhead.  For this reason, you
  723. should try to avoid situations (such as full call and non-specialized
  724. data structures) that force a descriptor representation.  See sections ?
  725. and ?.
  726.  
  727. *Note Floats:: for information on the extensions to support IEEE
  728. floating point.
  729.  
  730. 
  731. File: cmu-user.info  Node: Specialized Arrays, Prev: Floating Point Efficiency, Up: Numbers, Next: Interactions With Local Call
  732.  
  733. Specialized Arrays
  734. ------------------
  735.  
  736.  
  737. CMU Common Lisp supports specialized array element types through the :element-type
  738. argument to `make-array'.  When an array has a specialized element type, only
  739. elements of that type can be stored in the array.  From this restriction comes
  740. two major efficiency advantages:
  741.      
  742.    * A specialized array can save space by packing multiple elements
  743.      into a single word.  For example, a `base-char' array can have 4
  744.      elements per word, and a `bit' array can have 32.  This
  745.      space-efficient representation is possible because it is not
  746.      necessary to separately indicate the type of each element.
  747.      
  748.    * The elements in a specialized array can be given the same
  749.      non-descriptor representation as the one used in registers and on
  750.      the stack, eliminating the need for representation conversions when
  751.      reading and writing array elements.  For objects with pointer
  752.      descriptor representations (such as floats and word integers) there
  753.      is also a substantial consing reduction because it is not necessary
  754.      to allocate a new object every time an array element is modified.
  755.  
  756.  
  757.  
  758. These are the specialized element types currently supported:
  759.      
  760.      bit
  761.      (unsigned-byte 2)
  762.      (unsigned-byte 4)
  763.      (unsigned-byte 8)
  764.      (unsigned-byte 16)
  765.      (unsigned-byte 32)
  766.      base-character
  767.      single-float
  768.      double-float
  769.  
  770. Although a `simple-vector' can hold any type of object, true should
  771. still be considered a specialized array type, since arrays with element
  772. type true are specialized to hold descriptors.
  773.  
  774. When using non-descriptor representations, it is particularly important
  775. to make sure that array accesses are open-coded, since in addition to
  776. the generic operation overhead, efficiency is lost when the array
  777. element is converted to a descriptor so that it can be passed to (or
  778. from) the generic access routine.  You can detect inefficient array
  779. accesses by enabling efficiency notes, ?.  *Note Arrays::.
  780.  
  781. 
  782. File: cmu-user.info  Node: Interactions With Local Call, Prev: Specialized Arrays, Up: Numbers, Next: Representation of Characters
  783.  
  784. Interactions With Local Call
  785. ----------------------------
  786.  
  787.  
  788. Local call has many advantages (*Note Local Call::); one relevant to
  789. our discussion here is that local call extends the usefulness of non-descriptor
  790. representations.  If the compiler knows from the argument type that an argument
  791. has a non-descriptor representation, then the argument will be passed in that
  792. representation.  The easiest way to ensure that the argument type is known at
  793. compile time is to always declare the argument type in the called function,
  794. like:
  795.      
  796.      (defun 2+f (x)
  797.        (declare (single-float x))
  798.        (+ x 2.0))
  799.  
  800. The advantages of passing arguments and return values in a
  801. non-descriptor representation are the same as for non-descriptor
  802. representations in general: reduced consing and memory access (*Note
  803. Non-Descriptor Representations::.)  This extends the applicative
  804. programming styles discussed in section *Note Local Call:: to numeric
  805. code.  Also, if source files are kept reasonably small, block
  806. compilation can be used to reduce number consing to a minimum.
  807.  
  808. Note that non-descriptor return values can only be used with the known return
  809. convention (section *Note Return Values::.)  If the compiler can't prove that
  810. a function always returns the same number of values, then it must use the
  811. unknown values return convention, which requires a descriptor representation.
  812. Pay attention to the known return efficiency notes to avoid number consing.
  813.  
  814. 
  815. File: cmu-user.info  Node: Representation of Characters, Prev: Interactions With Local Call, Up: Numbers
  816.  
  817. Representation of Characters
  818. ----------------------------
  819.  
  820.  
  821. Python also uses a non-descriptor representation for characters when
  822. convenient.  This improves the efficiency of string manipulation, but is
  823. otherwise pretty invisible; characters have an immediate descriptor
  824. representation, so there is not a great penalty for converting a
  825. character to a descriptor.  Nonetheless, it may sometimes be helpful to
  826. declare character-valued variables as `base-character'.
  827.  
  828.  
  829. 
  830. File: cmu-user.info  Node: General Efficiency Hints, Prev: Numbers, Up: Advanced Compiler Use and Efficiency Hints, Next: Efficiency Notes
  831.  
  832. General Efficiency Hints
  833. ========================
  834.  
  835.  
  836. This section is a summary of various implementation costs and ways to
  837. get around them.  These hints are relatively unrelated to the use of the
  838. Python compiler, and probably also apply to most other Common Lisp
  839. implementations.  In each section, there are references to related
  840. in-depth discussion.
  841.  
  842. * Menu:
  843.  
  844. * Compile Your Code::           
  845. * Avoid Unnecessary Consing::   
  846. * Complex Argument Syntax::     
  847. * Mapping and Iteration::       
  848. * Trace Files and Disassembly::  
  849.  
  850.  
  851. 
  852. File: cmu-user.info  Node: Compile Your Code, Prev: General Efficiency Hints, Up: General Efficiency Hints, Next: Avoid Unnecessary Consing
  853.  
  854. Compile Your Code
  855. -----------------
  856.  
  857.  
  858. At this point, the advantages of compiling code relative to running it
  859. interpreted probably need not be emphasized too much, but remember that
  860. in CMU Common Lisp, compiled code typically runs hundreds of times
  861. faster than interpreted code.  Also, compiled (`fasl') files load
  862. significantly faster than source files, so it is worthwhile compiling
  863. files which are loaded many times, even if the speed of the functions in
  864. the file is unimportant.
  865.  
  866. Even disregarding the efficiency advantages, compiled code is as good or
  867. better than interpreted code.  Compiled code can be debugged at the
  868. source level (see chapter *Note The Debugger::), and compiled code does
  869. more error checking.  For these reasons, the interpreter should be
  870. regarded mainly as an interactive command interpreter, rather than as a
  871. programming language implementation.
  872.  
  873. Do not be concerned about the performance of your program until you see
  874. its speed compiled.  Some techniques that make compiled code run faster
  875. make interpreted code run slower.
  876.  
  877. 
  878. File: cmu-user.info  Node: Avoid Unnecessary Consing, Prev: Compile Your Code, Up: General Efficiency Hints, Next: Complex Argument Syntax
  879.  
  880. Avoid Unnecessary Consing
  881. -------------------------
  882.  
  883.  
  884.  Consing is another name for allocation of storage, as done by
  885. the `cons' function (hence its name.)  `cons' is by no means the only
  886. function which conses -- so does `make-array' and many other functions.
  887. Arithmetic and function call can also have hidden consing overheads.  Consing
  888. hurts performance in the following ways:
  889.      
  890.    * Consing reduces memory access locality, increasing paging activity.
  891.      
  892.    * Consing takes time just like anything else.
  893.      
  894.    * Any space allocated eventually needs to be reclaimed, either by
  895.      garbage collection or by starting a new `lisp' process.
  896.  
  897.  
  898.  
  899. Consing is not undiluted evil, since programs do things other than
  900. consing, and appropriate consing can speed up the real work.  It would
  901. certainly save time to allocate a vector of intermediate results that
  902. are reused hundreds of times.  Also, if it is necessary to copy a large
  903. data structure many times, it may be more efficient to update the data
  904. structure non-destructively; this somewhat increases update overhead,
  905. but makes copying trivial.
  906.  
  907. Note that the remarks in section *Note Writing Efficient Code:: about
  908. the importance of separating tuning from coding also apply to consing
  909. overhead.  The majority of consing will be done by a small portion of
  910. the program.  The consing hot spots are even less predictable than the
  911. CPU hot spots, so don't waste time and create bugs by doing unnecessary
  912. consing optimization.  During initial coding, avoid unnecessary
  913. side-effects and cons where it is convenient.  If profiling reveals a
  914. consing problem, THEN go back and fix the hot spots.
  915.  
  916. *Note Non-Descriptor Representations:: for a discussion of how to avoid
  917. number consing in Python.
  918.  
  919.  
  920. 
  921. File: cmu-user.info  Node: Complex Argument Syntax, Prev: Avoid Unnecessary Consing, Up: General Efficiency Hints, Next: Mapping and Iteration
  922.  
  923. Complex Argument Syntax
  924. -----------------------
  925.  
  926.  
  927. Common Lisp has very powerful argument passing mechanisms.  Unfortunately, two
  928. of the most powerful mechanisms, rest arguments and keyword arguments, have a
  929. significant performance penalty:
  930.      
  931.    * With keyword arguments, the called function has to parse the
  932.      supplied keywords by iterating over them and checking them against
  933.      the desired keywords.
  934.      
  935.    * With rest arguments, the function must cons a list to hold the
  936.      arguments.  If a function is called many times or with many
  937.      arguments, large amounts of memory will be allocated.
  938.  
  939.  
  940. Although rest argument consing is worse than keyword parsing, neither
  941. problem is serious unless thousands of calls are made to such a
  942. function.  The use of keyword arguments is strongly encouraged in
  943. functions with many arguments or with interfaces that are likely to be
  944. extended, and rest arguments are often natural in user interface
  945. functions.
  946.  
  947. Optional arguments have some efficiency advantage over keyword
  948. arguments, but their syntactic clumsiness and lack of extensibility has
  949. caused many CMU Common Lisp programmers to abandon use of optionals
  950. except in functions that have obviously simple and immutable interfaces
  951. (such as `subseq'), or in functions that are only called in a few
  952. places.  When defining an interface function to be used by other
  953. programmers or users, use of only required and keyword arguments is
  954. recommended.
  955.  
  956. Parsing of `defmacro' keyword and rest arguments is done at compile
  957. time, so a macro can be used to provide a convenient syntax with an
  958. efficient implementation.  If the macro-expanded form contains no
  959. keyword or rest arguments, then it is perfectly acceptable in inner
  960. loops.
  961.  
  962. Keyword argument parsing overhead can also be avoided by use of inline
  963. expansion (*Note Inline Expansion::) and block compilation (section
  964. *Note Block Compilation::.)
  965.  
  966. Note: the compiler open-codes most heavily used system functions which
  967. have keyword or rest arguments, so that no run-time overhead is
  968. involved.
  969.  
  970. 
  971. File: cmu-user.info  Node: Mapping and Iteration, Prev: Complex Argument Syntax, Up: General Efficiency Hints, Next: Trace Files and Disassembly
  972.  
  973. Mapping and Iteration
  974. ---------------------
  975.  
  976.  
  977. One of the traditional Common Lisp programming styles is a highly applicative one,
  978. involving the use of mapping functions and many lists to store intermediate
  979. results.  To compute the sum of the square-roots of a list of numbers, one
  980. might say:
  981.      
  982.      (apply #'+ (mapcar #'sqrt list-of-numbers))
  983.  
  984.  
  985. This programming style is clear and elegant, but unfortunately results
  986. in slow code.  There are two reasons why:
  987.      
  988.    * The creation of lists of intermediate results causes much consing
  989.      (see *Note Avoid Unnecessary Consing::).
  990.      
  991.    * Each level of application requires another scan down the list.
  992.      Thus, disregarding other effects, the above code would probably
  993.      take twice as long as a straightforward iterative version.
  994.  
  995.  
  996.  
  997. An example of an iterative version of the same code:
  998.      
  999.      (do ((num list-of-numbers (cdr num))
  1000.           (sum 0 (+ (sqrt (car num)) sum)))
  1001.          ((null num) sum))
  1002.  
  1003.  
  1004. See sections *Note Variable Type Inference:: and *Note Let
  1005. Optimization:: for a discussion of the interactions of iteration
  1006. constructs with type inference and variable optimization.  Also, section
  1007. *Note Local Tail Recursion:: discusses an applicative style of
  1008. iteration.
  1009.  
  1010. 
  1011. File: cmu-user.info  Node: Trace Files and Disassembly, Prev: Mapping and Iteration, Up: General Efficiency Hints
  1012.  
  1013. Trace Files and Disassembly
  1014. ---------------------------
  1015.  
  1016.  
  1017. In order to write efficient code, you need to know the relative costs of
  1018. different operations.  The main reason why writing efficient Common Lisp
  1019. code is difficult is that there are so many operations, and the costs of
  1020. these operations vary in obscure context-dependent ways.  Although
  1021. efficiency notes point out some problem areas, the only way to ensure
  1022. generation of the best code is to look at the assembly code output.
  1023.  
  1024. The `disassemble' function is a convenient way to get the assembly code
  1025. for a function, but it can be very difficult to interpret, since the
  1026. correspondence with the original source code is weak.  A better (but
  1027. more awkward) option is to use the :trace-file argument to
  1028. `compile-file' to generate a trace file.
  1029.  
  1030. A trace file is a dump of the compiler's internal representations, including
  1031. annotated assembly code.  Each component in the program gets three pages in
  1032. the trace file (separated by "`^L'"):
  1033.      
  1034.    * The implicit-continuation (or IR1) representation of the optimized
  1035.      source.  This is a dump of the flow graph representation used for
  1036.      "source level" optimizations.  As you will quickly notice, it is
  1037.      not really very close to the source.  This representation is not
  1038.      very useful to even sophisticated users.
  1039.      
  1040.    * The Virtual Machine (VM, or IR2) representation of the program.
  1041.      This dump represents the generated code as sequences of "Virtual
  1042.      OPerations" (VOPs.)  This representation is intermediate between
  1043.      the source and the assembly code -- each VOP corresponds fairly
  1044.      directly to some primitive function or construct, but a given VOP
  1045.      also has a fairly predictable instruction sequence.  An operation
  1046.      (such as `+') may have multiple implementations with different cost
  1047.      and applicability.  The choice of a particular VOP such as
  1048.      `+/fixnum' or `+/single-float' represents this choice of
  1049.      implementation.  Once you are familiar with it, the VM
  1050.      representation is probably the most useful for determining what
  1051.      implementation has been used.
  1052.      
  1053.    * An assembly listing, annotated with the VOP responsible for
  1054.      generating the instructions.  This listing is useful for figuring
  1055.      out what a VOP does and how it is implemented in a particular
  1056.      context, but its large size makes it more difficult to read.
  1057.  
  1058.  
  1059.  
  1060. Note that trace file generation takes much space and time, since the
  1061. trace file is tens of times larger than the source file.  To avoid huge
  1062. confusing trace files and much wasted time, it is best to separate the
  1063. critical program portion into its own file and then generate the trace
  1064. file from this small file.
  1065.  
  1066.  
  1067. 
  1068. File: cmu-user.info  Node: Efficiency Notes, Prev: General Efficiency Hints, Up: Advanced Compiler Use and Efficiency Hints, Next: Profiling
  1069.  
  1070. Efficiency Notes
  1071. ================
  1072.  
  1073.  
  1074. Efficiency notes are messages that warn the user that the compiler has
  1075. chosen a relatively inefficient implementation for some operation.
  1076. Usually an efficiency note reflects the compiler's desire for more type
  1077. information.  If the type of the values concerned is known to the
  1078. programmer, then additional declarations can be used to get a more
  1079. efficient implementation.
  1080.  
  1081. Efficiency notes are controlled by the `extensions:inhibit-warnings'
  1082. optimization quality (*Note The Optimize Declaration::.)  When `speed'
  1083. is greater than `extensions:inhibit-warnings', efficiency notes are
  1084. enabled.  Note that this implicitly enables efficiency notes whenever
  1085. `speed' is increased from its default of `1'.
  1086.  
  1087. Consider this program with an obscure missing declaration:
  1088.      
  1089.      (defun eff-note (x y z)
  1090.        (declare (fixnum x y z))
  1091.        (the fixnum (+ x y z)))
  1092.  
  1093. If compiled with `(speed 3) (safety 0)', this note is given:
  1094.      
  1095.      In: DEFUN EFF-NOTE
  1096.        (+ X Y Z)
  1097.      ==>
  1098.        (+ (+ X Y) Z)
  1099.      Note: Forced to do inline (signed-byte 32) arithmetic (cost 3).
  1100.            Unable to do inline fixnum arithmetic (cost 2) because:
  1101.            The first argument is a (INTEGER -1073741824 1073741822),
  1102.            not a FIXNUM.
  1103.  
  1104. This efficiency note tells us that the result of the intermediate computation
  1105. `(+ x y)' is not known to be a `fixnum', so the addition of the
  1106. intermediate sum to `z' must be done less efficiently.  This can be fixed by
  1107. changing the definition of `eff-note':
  1108.      
  1109.      (defun eff-note (x y z)
  1110.        (declare (fixnum x y z))
  1111.        (the fixnum (+ (the fixnum (+ x y)) z)))
  1112.  
  1113.  
  1114. * Menu:
  1115.  
  1116. * Type Uncertainty::            
  1117. * Efficiency Notes and Type Checking::  
  1118. * Representation Efficiency Notes::  
  1119. * Verbosity Control::           
  1120.  
  1121.  
  1122. 
  1123. File: cmu-user.info  Node: Type Uncertainty, Prev: Efficiency Notes, Up: Efficiency Notes, Next: Efficiency Notes and Type Checking
  1124.  
  1125. Type Uncertainty
  1126. ----------------
  1127.  
  1128.  
  1129. The main cause of inefficiency is the compiler's lack of adequate
  1130. information about the types of function argument and result values.
  1131. Many important operations (such as arithmetic) have an inefficient
  1132. general (generic) case, but have efficient implementations that can
  1133. usually be used if there is sufficient argument type information.
  1134.  
  1135. Type efficiency notes are given when a value's type is uncertain.  There is an
  1136. important distinction between values that are not known to be of a good
  1137. type (uncertain) and values that are known not to be of a good type.
  1138. Efficiency notes are given mainly for the first case (uncertain types.)  If it
  1139. is clear to the compiler that that there is not an efficient implementation for
  1140. a particular function call, then an efficiency note will only be given if the
  1141. `extensions:inhibit-warnings' optimization quality is `0' (*Note The Optimize Declaration::.)
  1142.  
  1143. In other words, the default efficiency notes only suggest that you add
  1144. declarations, not that you change the semantics of your program so that an
  1145. efficient implementation will apply.  For example, compilation of this form
  1146. will not give an efficiency note:
  1147.      
  1148.      (elt (the list l) i)
  1149.  
  1150. even though a vector access is more efficient than indexing a list.
  1151.  
  1152. 
  1153. File: cmu-user.info  Node: Efficiency Notes and Type Checking, Prev: Type Uncertainty, Up: Efficiency Notes, Next: Representation Efficiency Notes
  1154.  
  1155. Efficiency Notes and Type Checking
  1156. ----------------------------------
  1157.  
  1158.  
  1159. It is important that the `eff-note' example above used
  1160. `(safety 0)'.  When type checking is enabled, you may get apparently
  1161. spurious efficiency notes.  With `(safety 1)', the note has this extra
  1162. line on the end:
  1163.      
  1164.      The result is a (INTEGER -1610612736 1610612733), not a FIXNUM.
  1165.  
  1166. This seems strange, since there is a `the' declaration on the result of
  1167. that second addition.
  1168.  
  1169. In fact, the inefficiency is real, and is a consequence of Python's
  1170. treating declarations as assertions to be verified.  The compiler can't
  1171. assume that the result type declaration is true -- it must generate the
  1172. result and then test whether it is of the appropriate type.
  1173.  
  1174. In practice, this means that when you are tuning a program to run without type
  1175. checks, you should work from the efficiency notes generated by unsafe
  1176. compilation.  If you want code to run efficiently with type checking, then you
  1177. should pay attention to all the efficiency notes that you get during safe
  1178. compilation.  Since user supplied output type assertions (e.g., from `the')
  1179. are disregarded when selecting operation implementations for safe code, you
  1180. must somehow give the compiler information that allows it to prove that the
  1181. result truly must be of a good type.  In our example, it could be done by
  1182. constraining the argument types more:
  1183.      
  1184.      (defun eff-note (x y z)
  1185.        (declare (type (unsigned-byte 18) x y z))
  1186.        (+ x y z))
  1187.  
  1188. Of course, this declaration is acceptable only if the arguments to
  1189. `eff-note' always ARE `(unsigned-byte 18)' integers.
  1190.  
  1191. 
  1192.